package com.dpj.noLock;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class TestAccount {
    public static void main(String[] args) {
        Account account=new AccountCas(1000);
        Account.demo(account);
    }


}
//无锁方式解决

class  AccountCas implements Account{

    private AtomicInteger balance;

    public AccountCas(int balance) {
        this.balance = new AtomicInteger(balance);
    }

    @Override
    public Integer getBalance() {
        return balance.get();
    }

    @Override
    public void withdraw(Integer amount) {
//        while(true){
//            //获取余额的最新值
//            int prev = balance.get();
//            //要修改的余额
//            int next=prev-amount;
//            //真正修改
//            if (balance.compareAndSet(prev,next)) {
//                break;
//            }

        //这和上面注释掉的等同，都是getandadd这个方法底层就是采用了cas
        balance.getAndAdd(-1*amount);


        }

}

//有锁方式解决
class AccountUnsafe implements Account{
    private Integer balance;

    public AccountUnsafe(Integer balance) {
        this.balance = balance;
    }

    @Override
    public Integer getBalance() {
        synchronized (this){

            return this.balance;
        }
    }

    @Override
    public void withdraw(Integer amount) {
        synchronized (this){

            this.balance-=amount;
        }
    }
}
interface Account{
    //存款
    Integer getBalance();
    //取款
    void withdraw(Integer amount);
    /*
        方法回启动1000个线程，让每个线程做-10元操作
        如果初始为1000个线程，那么正确的结果应当是0
     */

    static void demo(Account account){
        List<Thread> ts=new ArrayList<>();
        for(int i=0;i<100;i++){
            ts.add(new Thread(()-> account.withdraw(10)));
        }
        long start = System.currentTimeMillis();
        ts.forEach(Thread::start);

        ts.forEach(t->{
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        long end = System.currentTimeMillis();
        System.out.println(account.getBalance()+"cost"+(end-start)/1000_000+"ms");
    }
}
